package dy.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mchange.v2.lang.StringUtils;
import dy.block.CommonUtil;
import dy.cache.Appcache;
import dy.dbserivce.IBusinessService;
import dy.dbserivce.IDealTaskerService;
import dy.dbserivce.IDeviceConfigService;
import dy.entity.DeviceConfig;
import dy.entity.ViewAccessServiceQuery;
import dy.ktv.CommunicationKtvProcessor;
import dy.ktv.KtvProcessor;
import dy.log.AppLogger;
import dy.mongo.MongoUtil;
import dy.type.DeviceIpMap;
import dy.type.DeviceLog;
import dy.type.DeviceMetaData;
import dy.type.PostConfigData;
import org.apache.mina.core.buffer.IoBuffer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@RestController
public class HttpConfigController {

    @Autowired
    Appcache appcache;

    @Autowired
    AppLogger appLogger;

    @Autowired
    KtvProcessor ktvProcessor;

    @Autowired
    IBusinessService businessService;

    @Autowired
    IDeviceConfigService deviceConfigService;

    @Autowired
    MongoUtil mongoUtil;

    @Autowired
    IDealTaskerService dealTaskerService;

    @Autowired
    CoapUtil coapUtil;

    @Value("${coap.config}")
    String coapConfig;

    @RequestMapping(value = "")
    public String deviceConfig(@RequestBody JSONObject json, HttpServletRequest request) throws Exception {
        appLogger.getLogger().info(String.format("data platform received config data [%s]", JSON.toJSON(json)));
        PostConfigData postConfigData = JSONObject.parseObject(json.toJSONString(), PostConfigData.class);
        DeviceConfig config = new DeviceConfig();
        config.setSn(StringUtils.nonEmptyOrNull(postConfigData.getSn()));
        config.setConfigid(StringUtils.nonEmptyOrNull(postConfigData.getConfigId()));
        config.setTimeservice(StringUtils.nonEmptyOrNull(postConfigData.getDeviceConfigData().getTimeservice()));
        config.setConfigtype(StringUtils.nonEmptyOrNull(postConfigData.getConfigtype()));
        config.setCreatedate(new Date());
        postConfigData.setDate(new Date());
        if (businessService.getBusinesskey(postConfigData.getBussinesskey()) < 0) {
            appLogger.getLogger().info(String.format("http can not find bussiness key[%s]", postConfigData.toString()));
        }

        //块协议
        if (postConfigData.getConfigtype().equals("block")) {
            //区分是否是ktv协议
            if (postConfigData.getDeviceConfigData().getPrivatedata() != null) {
                List<byte[]> listKtv = ktvProcessor.getKtvBytes(postConfigData.getDeviceConfigData().getPrivatedata());
                postConfigData.getDeviceConfigData().setConfighexdata(ktvProcessor.getKtvFrame(listKtv));
                config.setConfigdata(JSONArray.toJSONString(postConfigData.getDeviceConfigData().getPrivatedata()));
            } else if (postConfigData.getDeviceConfigData().getConfigdata() != null) {
                postConfigData.getDeviceConfigData().setConfighexdata(CommonUtil.hexString2Bytes(postConfigData.getDeviceConfigData().getConfigdata()));
                config.setConfigdata(postConfigData.getDeviceConfigData().getConfigdata());
            } else {
                return "data platform received http config parameters error";
            }
            //保存并发送配置
            deviceConfigService.saveConfig(config);
            sendBlockAndKtvConfig(config, postConfigData);
        }
        //纯ktv协议
        else if (postConfigData.getConfigtype().equals("rtu")) {
            //生成ktv的byte[]
            List<byte[]> listKtv = ktvProcessor.getKtvBytes(postConfigData.getDeviceConfigData().getPrivatedata());
            postConfigData.getDeviceConfigData().setConfighexdata(CommunicationKtvProcessor.getKtvConfigFrame(postConfigData.getSn(), listKtv));
            config.setConfigdata(JSONArray.toJSONString(postConfigData.getDeviceConfigData().getPrivatedata()));
            //保存并发送配置
            deviceConfigService.saveConfig(config);
            sendBlockAndKtvConfig(config, postConfigData);
        }
        //coap协议
        else if (postConfigData.getConfigtype().equals("coap")) {
            if (postConfigData.getDeviceConfigData().getPrivatedata() != null) {
                List<byte[]> listKtv = ktvProcessor.getKtvBytes(postConfigData.getDeviceConfigData().getPrivatedata());
                postConfigData.getDeviceConfigData().setConfighexdata(ktvProcessor.getKtvFrame(listKtv));
                config.setConfigdata(JSONArray.toJSONString(postConfigData.getDeviceConfigData().getPrivatedata()));
            } else if (postConfigData.getDeviceConfigData().getConfigdata() != null) {
                postConfigData.getDeviceConfigData().setConfighexdata(CommonUtil.hexString2Bytes(postConfigData.getDeviceConfigData().getConfigdata()));
                config.setConfigdata(postConfigData.getDeviceConfigData().getConfigdata());
            } else {
                return "data platform received http config parameters error";
            }
            deviceConfigService.saveConfig(config);
            sendCoapConfig(config, postConfigData);
        } else {
            return "data platform received http config parameters error";
        }
        return "data platform received nonconfig";
    }

    private void sendCoapConfig(DeviceConfig config, PostConfigData postConfigData) {
        //设备日志
        List<DeviceLog> ListDeviceLog = new ArrayList<>();
        boolean timeFlag = true;
        DeviceLog deviceLog;
        if (postConfigData.getDeviceConfigData().getTimeservice().equals("false")) {
            timeFlag = false;
            deviceLog = new DeviceLog(config.getSn(), 0, String.format("send time config to coap platform  [%s]  ", config.getConfigdata()), new Date());
        }else {
             deviceLog = new DeviceLog(config.getSn(), 0, String.format("send time config to coap platform  [%s]  ", config.getConfigdata()), new Date());
        }
        ListDeviceLog.add(deviceLog);
        Map<String, Object> coapCongfig = new HashMap<>();
        coapCongfig.put(coapConfig, config.getConfigdata());
        coapCongfig.put("msgid", config.getConfigdata().length());
        ViewAccessServiceQuery de = dealTaskerService.getBySn(config.getSn());
        if(de != null){
            coapUtil.sendconfig(de.getCoapdeviceid(), JSON.toJSONString(coapCongfig), timeFlag);
            mongoUtil.insertMongo(new ArrayList<DeviceMetaData>(), ListDeviceLog);
        }
    }


    private void sendBlockAndKtvConfig(DeviceConfig config, PostConfigData postConfigData) {
        //设备日志
        List<DeviceLog> ListDeviceLog = new ArrayList<>();
        if (postConfigData.getDeviceConfigData().getTimeservice().equals("false")) {
            DeviceLog deviceLog = new DeviceLog(config.getSn(), 0,
            String.format("device normal config into coap ", config.getConfigdata()), new Date());
            ListDeviceLog.add(deviceLog);

            //通用性配置
            ConcurrentHashMap<String, PostConfigData> postConfigDataConcurrentHashMap = appcache.getDeviceConfigMap().get(postConfigData.getSn());
            if (postConfigDataConcurrentHashMap == null) {
                postConfigDataConcurrentHashMap = new ConcurrentHashMap<>();
                postConfigDataConcurrentHashMap.put(postConfigData.getConfigId(), postConfigData);
                appcache.getDeviceConfigMap().put(postConfigData.getSn(), postConfigDataConcurrentHashMap);
            } else {
                postConfigDataConcurrentHashMap.put(postConfigData.getConfigId(), postConfigData);
                appcache.getDeviceConfigMap().put(postConfigData.getSn(), postConfigDataConcurrentHashMap);
            }
        } else {
            DeviceLog deviceLog = new DeviceLog(config.getSn(), 0, String.format("device time config [%s]", config.getConfigdata()), new Date());
            ListDeviceLog.add(deviceLog);
            //实时配置
            DeviceIpMap deviceIpMap = appcache.getDeviceIpMap().get(postConfigData.getSn());
            SocketAddress remote = new InetSocketAddress(deviceIpMap.getIp(), deviceIpMap.getPort());
            IoBuffer configData = IoBuffer.wrap(postConfigData.getDeviceConfigData().getConfighexdata());
            deviceIpMap.getAcceptor().newSession(remote, deviceIpMap.getAcceptor().getLocalAddress()).write(configData);
            appLogger.getLogger().info(String.format("send time config to device [%s] [%s]", JSON.toJSON(postConfigData), CommonUtil.byte2HexStr(postConfigData.getDeviceConfigData().getConfighexdata())));

            //更改配置状态
            config.setStatus("已发送");
            deviceConfigService.updateConfig(config);
        }
        mongoUtil.insertMongo(new ArrayList<DeviceMetaData>(), ListDeviceLog);
    }

}
